/**
 * 编程思路：使用非阻塞式IO完成，只使用一个线程完成
 */
package chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;

public class NioChatServer {
    private static ByteBuffer buffer = ByteBuffer.allocate(2048);
    private static List<SocketChannel> socketChannels = new ArrayList<>();

    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(9000));
        serverSocketChannel.configureBlocking(false);
        System.out.println("非阻塞式服务器启动，使用 telnet localhost 9000 登录");
        //以下是一个EeventLoop: 重复完成以下工作：
        //1. 是否有新的客户连接，如果有把相应的SocketChannel 加入channel列表中
        //2. 遍历channel列表，依次查看buffer中是否有新的数据，如果有将数据发送给所有的channel
        while (true) {
            SocketChannel socketChannel = serverSocketChannel.accept();
            if (socketChannel != null) {
                socketChannel.configureBlocking(false);
                socketChannels.add(socketChannel);
                System.out.println("有客户端连接");
                socketChannel.write(ByteBuffer.wrap(("你的端口是： "+socketChannel.socket().getPort()+"\n").getBytes()));
            }
            for (int i = 0; i < socketChannels.size(); i++) {
                SocketChannel skt = socketChannels.get(i);
                int len = skt.read(buffer);
                if (len > 0) {
                    String info = new String(buffer.array(),0,len);
                    buffer.clear();
                    send(skt, info);
                    if(info.startsWith("bye")){
                        skt.close();
                        socketChannels.remove(skt);
                        break;
                    }
                }
            }
        }
    }
    private static void send(SocketChannel channel, String info) {
        for (int i = 0; i < socketChannels.size(); i++) {
            SocketChannel channel1 = socketChannels.get(i);
            if (channel1 != channel) {
                try {
                    channel1.write(ByteBuffer.wrap((channel.socket().getPort()+"说: "+info).getBytes()));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
